// 封装 SqliteHelper 类

#include <sqlite3.h>
#include <string>
#include <iostream>

class SqliteHelper
{
public:
    /*int (*callback)(void*,int,char**,char**)
        void* : 是设置的在回调时传入的 arg 参数
        int：一行中数据的列数
        char**：存储一行数据的字符指针数组
        char**：每一列的字段名称
        这个回调函数有个 int 返回值，成功处理的情况下必须返回 0，返回非 0
        会触发 ABORT 退出程序
    */
    typedef int(*SqliteCallback)(void*, int, char**, char**);
    SqliteHelper(const std::string& filename)
    : _dbfile(filename),
      _handler(nullptr)
    {}

    bool open(int safe_level = SQLITE_OPEN_FULLMUTEX)
    {
        // int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs )
        int ret = sqlite3_open_v2(_dbfile.c_str(), &_handler, 
            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | safe_level, nullptr);
        if (ret != SQLITE_OK)
        {
            std::cout << "创建/打开sqlite3数据库失败！" << std::endl;
            std::cout << sqlite3_errmsg(_handler) << std::endl;
            return false;
        }
        return true;
    }

    bool exec(const std::string& sql, SqliteCallback scb, void* arg)
    {
        // int sqlite3_exec(sqlite3*, char *sql, int(*callback)(void*,int,char**,char**), 
        //                  void* arg, char **err)
        int ret = sqlite3_exec(_handler, sql.c_str(), scb, arg, nullptr);
        if (ret != SQLITE_OK)
        {
            std::cout << sql << std::endl;
            std::cout << "执行 sql 语句失败" << std::endl;
            std::cout << sqlite3_errmsg(_handler) << std::endl;
            return false;
        }
        return true;
    }

    void close()
    {
        if (_handler) sqlite3_close_v2(_handler);
    }
private:
    std::string _dbfile;
    sqlite3* _handler;
};